home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / CVTSS.C < prev    next >
Text File  |  1991-09-23  |  7KB  |  274 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)cvtss.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <ctype.h>
  10. #include <errno.h>
  11. #ifdef AC_STDDEF
  12. #include <stddef.h>
  13. #endif
  14. #include <stdio.h>
  15. #ifdef AC_STDLIB
  16. #include <stdlib.h>
  17. #endif
  18. #ifdef AC_STRING
  19. #include <string.h>
  20. #endif
  21.  
  22. /* local headers */
  23. #include "basstr.h"
  24.  
  25. /* macros */
  26. /* maximum of two values */
  27. #define max(a,b)    ((a) > (b) ? (a) : (b))
  28. /* minimum of two values */
  29. #define min(a,b)    ((a) < (b) ? (a) : (b))
  30.  
  31. /* macro to preserve characters within single and double quotes */
  32. #define QUOTES {                            \
  33.     char c = NUL;                            \
  34.     if (quotes && (*ps == '\'' || *ps == '\"')) {            \
  35.         c = *ps;                        \
  36.         *pt++ = *ps++;                        \
  37.         while (pt < ttend) {                    \
  38.             *pt++ = *ps;                    \
  39.             if (*ps == c || *ps == NUL) break;        \
  40.         }                            \
  41.         continue;                        \
  42.     }                                \
  43. }
  44.  
  45. /* function declarations */
  46. #ifdef AC_PROTO
  47. size_t    strnlen(const char *s, size_t n);
  48. #else
  49. size_t    strnlen();
  50. #endif
  51.  
  52. /*man---------------------------------------------------------------------------
  53. NAME
  54.      cvtss - convert string
  55.  
  56. SYNOPSIS
  57.      int cvtss(t, s, m, n)
  58.      char *t;
  59.      const char *s;
  60.      int m;
  61.      int n;
  62.  
  63. DESCRIPTION
  64.      The cvtss function takes the nul-terminated source string pointed
  65.      to by s, performs the conversions indicated by m, and places the
  66.      result in the target string pointed to by t.  n is the size of
  67.      the target string.  At most n characters are placed in t.
  68.  
  69.      Values for m are constructed by bitwise OR-ing flags from the
  70.      following list.  These macros are defined in basstr.h.
  71.  
  72.      CVT_TP               Trim the parity bit.
  73.      CVT_XSP              Discard spaces and tabs.
  74.      CVT_XCTL             Discard control characters.
  75.      CVT_XLEADSP          Discard leading spaces and tabs.
  76.      CVT_1SP              Reduce spaces and tabs to one space.
  77.      CVT_UPPER            Convert lowercase to uppercase.
  78.      CVT_BTOP             Convert [ to ( and ] to ).
  79.      CVT_XTRAILSP         Discard trailing spaces and tabs.
  80.      CVT_QUOTES           Do not alter characters inside single or
  81.                           double quotes except for parity bit
  82.                           trimming.
  83.  
  84.      cvtss will fail if one or more of the following is true:
  85.  
  86.      [EINVAL]       t or s is the NULL pointer.
  87.      [EINVAL]       n is less than 0.
  88.  
  89. DIAGNOSTICS
  90.      Upon successful completion, a value of 0 is returned.  Otherwise,
  91.      a value of -1 is returned, and errno set to indicate the error.
  92.  
  93. NOTES
  94.      cvtss is adapted directly from the BASIC function CVT$$.
  95.  
  96. ------------------------------------------------------------------------------*/
  97. #ifdef AC_PROTO
  98. int cvtss(char *t, const char *s, int m, int n)
  99. #else
  100. int cvtss(t, s, m, n)
  101. char *t;
  102. const char *s;
  103. int m;
  104. int n;
  105. #endif
  106. {
  107.     char *    ts    = NULL;        /* temporary source string */
  108.     char *    tt    = NULL;        /* temporary target string */
  109.     char huge *ttend= NULL;        /* first char past end of tt */
  110.     int    tn    = 0;        /* size of ts and tt */
  111.     int    quotes    = 0;        /* preserve quoted characters flag */
  112.     int    bit    = 0;        /* bit number */
  113.     char huge *ps    = NULL;        /* pointer into ts */
  114.     char huge *pt    = NULL;        /* pointer into tt */
  115.     int    flag    = 0;        /* gp flag */
  116.  
  117.     /* validate arguments */
  118.     if (t == NULL || s == NULL || n < 0) {
  119.         errno = EINVAL;
  120.         return -1;
  121.     }
  122.     if (n < 1) {
  123.         return 0;
  124.     }
  125.  
  126.     /* find size for ts */
  127.     tn = strlen(s) + 1;
  128.     tn = max(tn, n + 1);
  129.  
  130.     /* create temporary strings */
  131.     ts = (char *)calloc((size_t)tn, sizeof(*ts));
  132.     if (ts == NULL) {
  133.         errno = ENOMEM;
  134.         return -1;
  135.     }
  136.     tt = (char *)calloc((size_t)tn, sizeof(*tt));
  137.     if (tt == NULL) {
  138.         free(ts);
  139.         errno = ENOMEM;
  140.         return -1;
  141.     }
  142.     ttend = (char huge *)tt + tn;
  143.  
  144.     /* initialize ts with s */
  145.     strcpy(ts, s);
  146.     ts[tn - 1] = NUL;
  147.  
  148.     /* perform conversions */
  149.     quotes = m & CVT_QUOTES;    /* set preserve quoted chars flag */
  150.     for (bit = 0; m != 0; ++bit, m >>= 1) {
  151.         if (!(m & 1)) {
  152.             continue;
  153.         }
  154.         switch (bit) {
  155.         case 0:    /* trim the parity bit */
  156.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  157.                 QUOTES;
  158.                 *pt++ = *ps & 0x7F;
  159.                 if (*ps == NUL) break;
  160.             }
  161.             break;    /* case 0: */
  162.         case 1:    /* discard all spaces and tabs */
  163.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  164.                 QUOTES;
  165.                 if (!(*ps == ' ' || *ps == '\t')) {
  166.                     *pt++ = *ps;
  167.                 }
  168.                 if (*ps == NUL) break;
  169.             }
  170.             break;    /* case 1: */
  171.         case 2:    /* discard all control characters */
  172.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  173.                 QUOTES;
  174.                 if (*ps == '\t') {
  175.                     *pt++ = ' ';
  176.                 } else if (!iscntrl(*ps)) {
  177.                     *pt++ = *ps;
  178.                 }
  179.                 if (*ps == NUL) break;
  180.             }
  181.             /* nul terminate if shorter than size */
  182.             if (pt < ttend) {
  183.                 *pt++ = NUL;
  184.             }
  185.             break;    /* case 2: */
  186.         case 3:    /* discard leading spaces and tabs */
  187.             for (ps = ts; *ps == ' ' || *ps == '\t'; ++ps) {
  188.             }
  189.             strncpy(tt, (char *)ps, n);
  190.             break;    /* case 3: */
  191.         case 4:    /* reduce spaces and tabs to one space */
  192.             flag = 0;
  193.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  194.                 QUOTES;
  195.                 if (flag) {
  196.                     if (*ps != ' ' && *ps != '\t') {
  197.                         *pt++ = *ps;
  198.                         flag = 0;
  199.                     }
  200.                 } else {
  201.                     if (*ps == ' ' || *ps == '\t') {
  202.                         *pt++ = ' ';
  203.                         flag = 1;
  204.                     } else {
  205.                         *pt++ = *ps;
  206.                     }
  207.                 }
  208.                 if (*ps == NUL) break;
  209.             }
  210.             break;    /* case 4: */
  211.         case 5:    /* convert lowercase to uppercase */
  212.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  213.                 QUOTES;
  214.                 *pt++ = toupper(*ps);
  215.                 if (*ps == NUL) break;
  216.             }
  217.             break;    /* case 5: */
  218.         case 6:    /* convert [ to ( and ] to ) */
  219.             for (ps = ts, pt = tt; pt < ttend; ++ps) {
  220.                 QUOTES;
  221.                 if (*ps == '[') *pt = '(';
  222.                 else if (*ps == ']') *pt = ')';
  223.                 else *pt = *ps;
  224.                 ++pt;
  225.                 if (*ps == NUL) break;
  226.             }
  227.             break;    /* case 6: */
  228.         case 7:    /* discard trailing spaces and tabs */
  229.             for (ps = (char huge *)ts + strnlen(ts, tn) - 1; ps >= (char huge *)ts; --ps) {
  230.                 if (*ps != ' ' && *ps != '\t') break;
  231.             }
  232.             ts[min(tn - 1, ps + 1 - (char huge *)ts)] = NUL;
  233.             strncpy(tt, ts, tn);
  234.             break;    /* case 7: */
  235.         case 8:    /* do not alter characters inside quotes */
  236.             /* see QUOTES macro */
  237.             continue;
  238.             break;    /* case 8: */
  239.         default:
  240.             free(tt);
  241.             free(ts);
  242.             errno = EINVAL;
  243.             return -1;
  244.             break;
  245.         }
  246.         strncpy(ts, tt, tn);
  247.     }
  248.  
  249.     /* load target string */
  250.     strncpy(t, ts, n);
  251.  
  252.     /* free temporary strings */
  253.     free(tt);
  254.     free(ts);
  255.  
  256.     return 0;
  257. }
  258.  
  259. /* strnlen:  return length of string of size n */
  260. #ifdef AC_PROTO
  261. size_t strnlen(const char *s, size_t n)
  262. #else
  263. size_t strnlen(s, n)
  264. const char *s;
  265. size_t n;
  266. #endif
  267. {
  268.     size_t    i;
  269.  
  270.     for (i = 0; s[i] != NUL && i < n; ++i);
  271.  
  272.     return i;
  273. }
  274.